/* Copyright  2009
   @Author
   Richard Changde Yin            e-mail yinchangde@hotmail.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
#ifndef ___DEBUG_H___
#define ___DEBUG_H___

#include<error.h>


extern int DebugDM_Alloc;
extern int DebugDM_VarAlloc;
extern int DebugDM_Lock;
extern int DebugDM_Transaction;
extern int DebugDM_UndoLog;
extern int DebugDM_RedoLog;
extern int DebugDM_Index;
extern int DebugDM_HashIndex;
extern int DebugDM_TreeIndex;
extern int DebugDM_SystemDatabase;
extern int DebugDM_Database;
extern int DebugDM_Table;
extern int DebugDM_Predicate;
extern int DebugDM_Iterator;
extern int DebugDM_Process;
extern int DebugDM_Network;
extern int DebugDM_Gateway;
extern int DebugDM_Adapter;
extern int DebugDM_SqlLog;


extern int printError1(BackEnd::DbRetVal val, char* fname, int lno, char *format, ...);

#define printError(a, ...) printError1(a, __FILE__, __LINE__, __VA_ARGS__)

enum DebugModule
{
    DM_Alloc = 0,
    DM_VarAlloc,
    DM_Lock,
    DM_Transaction,
    DM_UndoLog,
    DM_RedoLog,
    DM_Index,
    DM_HashIndex,
    DM_TreeIndex,
    DM_SystemDatabase,
    DM_Database,
    DM_Table,
    DM_Predicate,
    DM_Iterator,
    DM_Process,
    DM_Network,
    DM_Gateway,
    DM_Adapter,
    DM_SqlLog
};

extern char moduleNames[][20];
extern char     levelNames[][10]    ;



extern int printDebug1(int module, char *fname, int lineno, char *format, ...);


#ifdef DEBUG
#define printDebug(a, ...) printDebug1(a, __FILE__, __LINE__, __VA_ARGS__)
#else
#define printDebug(...) ;
#endif

//Logging

#define MAX_TRACE_LOG_LENGTH 1024

enum LogLevel
{
    LogOff = 0,
    LogFine,
    LogFiner,
    LogFinest
};


#include<mutex.h>
class Logger
{
    Mutex mutex_; //guard in case of multi threaded programs

    int fdLog;  //file descriptor

    LogLevel configLevel;   //configuration file setting is cached here.
public:
    int log(LogLevel level, char* filename, int lineNo, char *format, ...);
    int createLogRecord(LogLevel level, char* filename, int lineNo,
                        char* message,
                        char **in);
    BackEnd::DbRetVal startLogger(char *filename, bool isCreate = false);
    void stopLogger();
};

//Global object
static Logger logger;

#define logFinest(logger, ...) \
{\
  (logger).log(LogFinest, __FILE__, __LINE__, __VA_ARGS__);\
};

#define logFiner(logger, ...) \
{\
  (logger).log(LogFiner, __FILE__, __LINE__, __VA_ARGS__);\
};

#define logFine(logger, ...) \
{\
  (logger).log(LogFine, __FILE__, __LINE__, __VA_ARGS__);\
};


#endif
